package org.linlinjava.litemall.wx.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.constant.LitemallWXMembershipLevelConstants;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.payment.DefaultCurType;
import org.linlinjava.litemall.core.payment.PaymentResponseCode;
import org.linlinjava.litemall.core.payment.paypal.service.impl.GoodsPaypalServiceImpl;
import org.linlinjava.litemall.core.util.GeneratorUtil;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.LitemallAccountBookFormDto;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderHandleOption;
import org.linlinjava.litemall.db.util.OrderStatusUtil;
import org.linlinjava.litemall.wx.constant.LitemallWXConstants;
import org.linlinjava.litemall.wx.util.RewardsUtils;
import org.linlinjava.litemall.wx.util.WxResponseEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author ：stephen
 * @date ：Created in 2020/4/10 13:52
 * @description：用户余额支付
 */
@Service
public class WxBalancePayService {
    private static final Log log = LogFactory.getLog(WxBalancePayService.class);

    @Autowired
    private LitemallUserService litemallUserService;
    @Autowired
    private NoticeHelper noticeHelper;
    @Autowired
    private LitemallRechargeConsumptionService litemallRechargeConsumptionService;
    @Autowired
    private LitemallOrderService litemallOrderService;
    @Autowired
    private LitemallAccountBookService litemallAccountBookService;

    @Autowired
    private GoodsPaypalServiceImpl paypalService;

    @Autowired
    private RewardsUtils rewardsUtils;


    @Autowired
    private LumiereMemberWelfareCouponService lumiereMemberWelfareCouponService;


    @Autowired
    private LumiereMemberWelfareSubscribeService lumiereMemberWelfareSubscribeService;

    @Autowired
    private LumierelLevelMemberService lumierelLevelMemberService;

    @Autowired
    private LumiereSubscribeUserService lumiereSubscribeUserService;

    @Autowired
    private LitemallGiftCardService litemallGiftCardService;

    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;

    @Autowired
    private LumiereSubscribeRuleService lumiereSubscribeRuleService;
    @Autowired
    private LitemallCouponService litemallCouponService;

    @Autowired
    private LitemallCouponUserService litemallCouponUserService;

    /**
     * 余额支付订单
     * @param userId
     * @param body
     * @return
     */
    @Transactional
    public  Object pay(Integer userId, String body){
        log.info("enter pay start " + body);
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if(orderId == null){
            return ResponseUtil.badArgument(WxResponseEnum.BAD_ARGUMENT_ORDERID);
        }

        LitemallOrder order = litemallOrderService.findById(orderId);
        // 检测订单是否能够支付
        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isPay()) {
            return ResponseUtil.fail(PaymentResponseCode.ORDER_INVALID_OPERATION, "订单不能支付");
        }

        LitemallUser user = litemallUserService.findById(userId);
        if(user == null){
            return ResponseUtil.badArgument(WxResponseEnum.IS_NULL_CARD);
        }
        if(user.getAvailableAmount().compareTo(order.getActualPrice()) < 0){
            return ResponseUtil.badArgument(WxResponseEnum.NOT_ENOUGH_AMOUNT);
        }
        //是否第一次消费
        rewardsUtils.getRewardInConsum(userId);

        // 检查这个订单是否已经处理过
        if (OrderStatusUtil.isPayStatus(order) || order.getPayId() != null) {
            return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, order.getOrderSn() + "订单已经处理成功!");
        }
        LitemallRechargeConsumption litemallRechargeConsumption = saveLog(order, user, Constants.LOG_GIFTCARD_CONSUME);

        order.setPayType(Constants.ORDER_PAY_TYPE_BALANCE);
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setPayTime(LocalDateTime.now());
//        order.setOrderStatus(OrderUtil.STATUS_PAY);
        order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);
        order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
        order.setPayId(String.valueOf(litemallRechargeConsumption.getId()));        //将消费日志id作为支付id
        order.setTransationId(String.valueOf(litemallRechargeConsumption.getId())); //将消费日志id作为transation id
        litemallOrderService.updateById(order);


        //更新订单
        /*if (litemallOrderService.updateWithOptimisticLocker(order) == 0) {
            // 这里可能存在这样一个问题，用户支付和系统自动取消订单发生在同时
            // 如果数据库首先因为系统自动取消订单而更新了订单状态；
            // 此时用户支付完成回调这里也要更新数据库，而由于乐观锁机制这里的更新会失败
            // 因此，这里会重新读取数据库检查状态是否是订单自动取消，如果是则更新成支付状态。
            order = litemallOrderService.findBySn(order.getOrderSn());
            int updated = 0;
//            if (OrderUtil.isAutoCancelStatus(order)) {
            if (OrderStatusUtil.isCancelStatus(order)) {
                order.setPayTime(LocalDateTime.now());
//                order.setOrderStatus(OrderUtil.STATUS_PAY);
                order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);
                order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
                updated = litemallOrderService.updateWithOptimisticLocker(order);
            }

            // 如果updated是0，那么数据库更新失败
            if (updated == 0) {
                return ResponseUtil.updatedDateExpired();
            }
        }*/
        //更新用户余额
        user.setAvailableAmount(user.getAvailableAmount().subtract(order.getActualPrice()));
        litemallUserService.updateById(user);

        paypalService.presentPoint(orderId,litemallRechargeConsumption.getId());
        //用户 等级会员的提升
        paypalService.upgradeUserLevel(orderId);

        //添加收款记录
    	LitemallAccountBookFormDto form = new LitemallAccountBookFormDto();
    	Integer shopId = order.getShopId();
    	form.setShopId(shopId);
    	form.setRecordType(0);
    	form.setRecordDate(LocalDateTime.now());
    	form.setAmount(order.getActualPrice());
    	form.setRemark("app order");
    	form.setSourceType(Constants.BOOK_SOURCE_TYPE_ORDER);
    	litemallAccountBookService.create(shopId, form);


        //发送订单支付成功通知
        noticeHelper.noticeUser(Constants.MSG_TYPE_ORDER,"Order payment", order.getOrderSn()+"Order payment succeeded", userId, order);
        //发送已支付订单到pos系统，门店开始制作商品
//        noticeHelper.noticeShop(Constants.MSG_TYPE_ORDER, JSON.toJSONString(order), order.getShopId());

        // 推送厨房端
//    	posPushSender.pushAll(order.getShopId(), Constants.ORDER_PUSH_TYPE_PAID, null);

        return ResponseUtil.ok();
    }

    /**
     * 记录日志并返回
     * @param order
     * @return
     */
    @Transactional
    public LitemallRechargeConsumption saveLog(LitemallOrder order, LitemallUser user, Byte type){
        LitemallRechargeConsumption log = new LitemallRechargeConsumption();
        log.setAmount(order.getActualPrice());
        log.setAddUserId(user.getId());
        log.setOrderId(order.getId());
        log.setUserId(user.getId());
        log.setUsername(user.getUsername());
        log.setMobile(user.getMobile());
        log.setPoints(user.getPoints());
        log.setType(type);
        log.setUserLevel(user.getUserLevel());
        log.setAvailableAmount(user.getAvailableAmount().subtract(order.getActualPrice()));
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        litemallRechargeConsumptionService.add(log);
        return log;
    }


    /**
     * 用户购买，等级会员升级
     */

    public void welfareGift(Integer memberId, LitemallUser giveeUser,
                            String userName, Integer userId, LumiereLevelMember levelMember, LocalDateTime endT) {
        //添加优惠券
        List<LumiereMemberWelfareCoupon> welfareCoupons = lumiereMemberWelfareCouponService.findByMemberId(memberId, (byte) 1);

        welfareCoupons.stream().forEach(welfareCoupon -> {
            Integer couponNum = welfareCoupon.getNumbers();
            LitemallCoupon coupon = litemallCouponService.findById(welfareCoupon.getCouponId());

            if (coupon != null) {
                LocalDateTime startT = coupon.getStartTime();

                for (Integer i = 0; i < couponNum; i++) {
                    LitemallCouponUser litemallCouponUser = new LitemallCouponUser();
                    litemallCouponUser.setStartTime(startT);
                    litemallCouponUser.setEndTime(coupon.getEndTime());
                    litemallCouponUser.setStatus((short) 0);
                    litemallCouponUser.setCouponId(coupon.getId());
                    litemallCouponUser.setAddTime(LocalDateTime.now());
                    litemallCouponUser.setUpdateTime(LocalDateTime.now());
                    litemallCouponUser.setDeleted(false);
                    litemallCouponUser.setUserId(giveeUser != null ? giveeUser.getId() : userId);
                    litemallCouponUser.setUserName(userName);
                    litemallCouponUserService.add(litemallCouponUser);
                }
            }
        });

        //添加用户订阅
        List<LumiereMemberWelfareSubscribe> welfareSubscribes = lumiereMemberWelfareSubscribeService.findByMemberId(memberId, (byte) 1);

        welfareSubscribes.stream().forEach(welfareSubscribe -> {
            Integer[] selectRuleIds = welfareSubscribe.getSubscribeRuleIds();
            LumiereSubscribeUser subscribeUser = addSubscribeUser(userId, welfareSubscribe.getSubscribeId(), selectRuleIds, endT, userName, giveeUser);
            lumiereSubscribeUserService.add(subscribeUser);
        });


        //添加礼物卡
        if (levelMember.getGiftCardIds() != null) {
            Integer[] giftCardIds = levelMember.getGiftCardIds();
            for (int i = 0; i < giftCardIds.length; i++) {
                LitemallGiftCard litemallGiftCard = litemallGiftCardService.findById(giftCardIds[i]);
                if (litemallGiftCard != null) {
                    LitemallGiftCardUser giftCardUser = new LitemallGiftCardUser();
                    giftCardUser.setIsDefault(0);

                    String cardNumber = GeneratorUtil.cardNumberGenerator("00", userId);
                    LitemallGiftCardUser cardUser = litemallGiftCardUserService.findByNumber(cardNumber);
                    while (cardUser != null) {
                        cardNumber = GeneratorUtil.cardNumberGenerator("00", userId);
                        cardUser = litemallGiftCardUserService.findByNumber(cardNumber);
                    }
                    giftCardUser.setCardNumber(cardNumber);
                    giftCardUser.setUserId(giveeUser != null ? giveeUser.getId() : userId);
                    giftCardUser.setAmount(BigDecimal.ZERO);
                    giftCardUser.setStatus(0);
                    giftCardUser.setDeleted(false);
                    giftCardUser.setAddTime(LocalDateTime.now());
                    giftCardUser.setUpdateTime(LocalDateTime.now());
                    giftCardUser.setGiftCardId(giftCardIds[i]);
                    litemallGiftCardUserService.add(giftCardUser);
                }
            }
        }
        LumiereLevelMember nextLevelMember = lumierelLevelMemberService.getOne(Wrappers.lambdaQuery(LumiereLevelMember.class)
                .eq(LumiereLevelMember::getPid,levelMember.getId()));
        //String nextLevel = "\r\n The next level :"+nextLevelMember.getName()+",Upgrade Rules :need to consume "+(nextLevelMember.getSaveLevelPoint()==null? String.valueOf(nextLevelMember.getSaveLevelMoney()) :nextLevelMember.getSaveLevelMoney()+"");
        //发送系统消息
        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,
                LitemallWXMembershipLevelConstants.WX_MEMBERSHIP_LEVEL_TITLE_NOTICEHELPER,
                String.format(LitemallWXMembershipLevelConstants.WX_MEMBERSHIP_LEVEL_UPGRADE_NOTICEHELPER,nextLevelMember.getName()),userId,nextLevelMember);
    }

    public LumiereSubscribeUser addSubscribeUser(Integer userId, Integer subscribeId, Integer[] selectRuleIds,
                                                 LocalDateTime endT, String givee, LitemallUser giveeUser) {

        LitemallUser user = litemallUserService.findById(userId);

        LumiereSubscribeUser lumiereSubscribeUser = new LumiereSubscribeUser();
        lumiereSubscribeUser.setPurchaserId(userId);
        if (lumiereSubscribeUser.getUserId() == null) {
            lumiereSubscribeUser.setUserId(giveeUser != null ? giveeUser.getId() : userId);
        }

        LumiereSubscribeRule rule = lumiereSubscribeRuleService.findById(selectRuleIds[0]);

        lumiereSubscribeUser.setSubscribeId(subscribeId);

        lumiereSubscribeUser.setStatus(Constants.SUBSCRIBE_USER_MEMBER_NOT_CONFIRM);

        lumiereSubscribeUser.setAutoSub(false);

        lumiereSubscribeUser.setPurchaserId(giveeUser != null ? giveeUser.getId() : userId);

        lumiereSubscribeUser.setUserName(giveeUser != null ? giveeUser.getUsername() : user != null ? user.getUsername() : null);

        lumiereSubscribeUser.setPrice(BigDecimal.ZERO);

        lumiereSubscribeUser.setStartTime(LocalDateTime.now());

        if(rule != null) {
            if (rule.getRuleType().equals((byte) 1)) {
                lumiereSubscribeUser.setEndTime(LocalDateTime.now().plusWeeks(1));
            } else if (rule.getRuleType().equals((byte) 2)) {
                lumiereSubscribeUser.setEndTime(LocalDateTime.now().plusMonths(1));
            } else {
                lumiereSubscribeUser.setEndTime(LocalDateTime.now().plusYears(1));
            }
        }
        lumiereSubscribeUser.setRuleId(selectRuleIds[0]);

        return lumiereSubscribeUser;
    }

}
